using System.Collections;
using System.Collections.Generic;
using UnityEngine;

namespace Factory
{
    public class HeatMapGenericVisual : MonoBehaviour
    {
        private Grid<HeatMapGridObject> grid_;
        private Mesh mesh_;
        private bool updateMesh_;
        // Start is called before the first frame update

        private void Awake()
        {
            mesh_ = new Mesh();
            GetComponent<MeshFilter>().mesh = mesh_;
        }

        public void SetGrid(Grid<HeatMapGridObject> grid)
        {
            grid_ = grid;
            UpdateHeatMapVisual();

            grid_.OnGridObjectChanged += Grid_OnGridValueChaned;
        }

        void Start()
        {

        }

        // Update is called once per frame
        void Update()
        {

        }

        private void LateUpdate()
        {
            if (updateMesh_)
            {
                updateMesh_ = false;
                UpdateHeatMapVisual();
            }
        }

        void Grid_OnGridValueChaned(object sender, Grid<HeatMapGridObject>.GridObjectChangedEventArgs args)
        {
            updateMesh_ = true;
        }

        private void UpdateHeatMapVisual()
        {
            Utils.CreateEmptyMeshArrays(grid_.GetWidth() * grid_.GetHeight(), out var vertices, out var uv, out var triangles);
            for (int x = 0; x < grid_.GetWidth(); ++x)
            {
                for (int y = 0; y < grid_.GetHeight(); ++y)
                {
                    int index = x * grid_.GetWidth() + y;
                    var quadSize = new Vector3(1, 1) * grid_.GetCellSize();

                    HeatMapGridObject gridObj = grid_.GetGridObject(x, y);
                    var gridValueNormal = gridObj.GetValueNormalized();
                    Vector2 gridValUv = new Vector2(gridValueNormal, 0f);
                    Utils.AddToMeshArrays(vertices, uv, triangles,
                        index, grid_.GetWorldPosition(x, y) + quadSize * .5f,
                        0f, quadSize, gridValUv, gridValUv);
                }
            }
            mesh_.vertices = vertices;
            mesh_.uv = uv;
            mesh_.triangles = triangles;
        }
    }

    public class HeatMapGridObject
    {
        private const int MIN = 0;
        private const int MAX = 100;

        private Grid<HeatMapGridObject> grid;
        private int x;
        private int y;
        private int value;

        public HeatMapGridObject(Grid<HeatMapGridObject> grid, int x, int y)
        {
            this.grid = grid;
            this.x = x;
            this.y = y;
        }

        public void AddValue(int addValue)
        {
            value += addValue;
            value = Mathf.Clamp(value, MIN, MAX);
            grid.TriggerGridObjectChanged(x, y);
        }

        public float GetValueNormalized()
        {
            return (float)value / MAX;
        }

        public override string ToString()
        {
            return value.ToString();
        }
    }
}
